﻿/* util.c */

#include "util.h"

static Node *node_create();

/**
 *	Function	: read_file
 *	Param In	: filename: 要读取文件的路径
 *	Param Out	: 无
 *	Return Val	: 返回缓冲区的地址
 *	Dscription	: 将文件的内容读入缓冲区，并返回缓冲区的地址
 *	Date		: 2016/May/08  04:10:41 PM
 */
char *read_file(char *filename){
	FILE *fp = NULL;
	struct stat buf;
	if((fp = fopen(filename, "r")) == NULL){
		printf("Open file faild!\n");
		exit (1);
	}

	stat(filename, &buf);						//返回文件的信息
	char *buffer = (char *)malloc(sizeof(char) * buf.st_size + 1);
	memset(buffer, 0, buf.st_size + 1);			//初始化内存
	if(fread(buffer, 1, buf.st_size, fp) == 0){	//如果读取数据失败，直接退出程序
		printf("Read file error!");
		exit (1);
	}

	fclose(fp);
	return buffer;
}

/**
 *	Function	: create_tree
 *	Param In	: buf: 缓冲区的地址
 *	Param Out	: 无
 *	Return Val	: 返回树根结点的地址
 *	Dscription	: 将缓冲区的内容创建成一棵树，并返回树根结点
 *	Date		: 2016/May/08  04:10:57 PM
 */
Node *create_tree(char *buf){
	Stack *s = stack_create(); //创建一个栈
	char *p = strchr(buf, '<'), *q = p;//初始化p,q的位置
	Node *root = NULL;
	char tag_buf[50] = {0};
	char context_buf[50] = {0};
	do{
		if(q[1] != '/'){//为起始标签
			q = strchr(p, '>');
			snprintf(tag_buf, q - p, "%s", p + 1); //保存标签
			p = q;
			q = strchr(p, '<');
			if(q[1] != '/'){
				Node *temp = node_create(tag_buf, NULL);
				push(s, temp);
				p = q;
			}else{//标签结束
				snprintf(context_buf, q - p, "%s", p + 1);
				Node *temp = node_create(tag_buf, context_buf);
				if(stack_size(s) != 0){			//栈不为空的话
					Node *parent = getHead(s);	//临时保存父结点
					if(parent->child == NULL){	//此时说明父结点没有孩子结点
						parent->child = temp;
						parent->last_child = temp;
						temp->parent = parent;
						temp->prev = temp;
						temp->next = temp;;
					}else{
						parent->last_child->next = temp;
						parent->child->prev = temp;
						temp->parent = parent;
						temp->prev = parent->last_child;
						temp->next = parent->child;
						parent->last_child = temp;
					}
				}
				p = q + 1;
				q = strchr(p, '<');//p的当前位置就是'/',所就从它的下一个开始找
				p = q;
			}
		}else{//为结束标签
			type_t pNode = NULL;
			pop(s, &pNode);
			if(stack_size(s) != 0){			//栈不为空的话
				Node *parent = getHead(s);	//临时保存父结点
				if(parent->child == NULL){	//此时说明父结点没有孩子结点
					parent->child = pNode;
					parent->last_child = pNode;
					pNode->parent = parent;
					pNode->prev = pNode;
					pNode->next = pNode;
				}else{
					parent->last_child->next = pNode;
					parent->child->prev = pNode;
					pNode->parent = parent;
					pNode->prev = parent->last_child;
					pNode->next = parent->child;
					parent->last_child = pNode;
				}
				p = q + 1;
				q = strchr(p, '<');
				p = q;
			}else{
				root = pNode;
			}
		}
	}while(stack_size(s) != 0); //当栈为空时，退出循环
	return root;
}

/**
 *	Function	: node_create
 *	Param In	: tag: 标签名
 *				  context: 标签的具体内容
 *	Param Out	: 无
 *	Return Val	: 返回结点指针
 *	Dscription	: 创建一个结点，并返回结点指针，内部函数
 *	Date		: 2016/May/08  04:57:27 PM
 */
static Node *node_create(char *tag, char *context){
	Node *p = (Node *)malloc(sizeof(Node));
	memset(p, 0, sizeof(Node));
	p->tag = (char *)malloc(strlen(tag) + 1);
	memcpy(p->tag, tag, strlen(tag) + 1);
	if(context != NULL){
		p->context = (char *)malloc(strlen(context) + 1);
		memcpy(p->context, context, strlen(context ) + 1);
	}
	return p;
}

/**
 *	Function	:
 *	Param In	:
 *	Param Out	:
 *	Return Val	:
 *	Dscription	:
 *	Date		: 2016/May/11  07:18:26 PM
 */
void destroy_tree(Node **root){
	Node *p = *root;
	if(p->child == NULL){//此时为枝叶结点
		Node *parent = p->parent;
		if(p->next != p){//有兄弟结点
			parent->child = p->next;
			parent->child->prev = parent->last_child;
			free(p);
			return;
		}else{			//没有兄弟结点
			parent->child = NULL;
			free(p);
			return;
		}
	}else{//不是枝叶结点
		while(p->child != p->last_child){
			destroy_tree(&p->child);
		}
		destroy_tree(&p->child);
	}
}
